# This file is used to import data from Version control

import sys
import subprocess
from git import *
from couchdbkit import *
import time
import threading
import Queue
import pysvn

from commit import Commit

tempDir = "/tmp"
goodCloneReply = "Cloning into "

################################## GIT #####################################################################

def cloneRepoLocally(repoAddress):
    # clone the given git repository locally 
    # return the name of the directory created or False if something went wrong 
    command = "cd "+tempDir+" && git clone "+repoAddress+ " && exit"
    print command
    out = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    reply=out.stdout.read()
    if reply.startswith(goodCloneReply):
        s = reply.replace(goodCloneReply, "")
        s = s.replace("...", "")
        s = s.replace("\n", "")
        s = s.replace("'", "")
        return s
    else:
        return False
    
def importGit(localRepoPath, couchdb, database, project):
    #import the local repository into the given couchdb database with the specified name
    repo = Repo(localRepoPath)
    
    # get commit list
    commits = repo.iter_commits()
    num_commits = 0
    comm_list = []
    start_explore = time.clock()
    server = Server(couchdb)
    db = server.get_or_create_db(database)
    stored = 0
    for c in commits:        
        commit = Commit()
        commit.createCommit(c.committed_date, c.author, c.committer, c.summary, c.name_rev, c.stats.files, project)       
        comm_list.append(commit)       
        num_commits +=1
        if(num_commits%100 == 0):
            sys.stdout.write('.')
            sys.stdout.flush()
            #save commit in couchdb
            for c in comm_list:
                ex = c.commitToDatabase(server, db)
                if ex:
                    stored += 1
            comm_list = [] # empty list
    for c in comm_list:
        ex = c.commitToDatabase(server, db)
        if ex:
            stored += 1
    comm_list = [] # empty list
    end_explore = time.clock()
   

    
    return num_commits, stored, end_explore-start_explore

class MainGitThread(threading.Thread):
    # thread to import in couchdb commits from git 
    
    def __init__(self, repo, couchdb, database, project):
        threading.Thread.__init__(self)
        self.repo = repo # repository address
        self.couchdb = couchdb # couchdb address
        self.database = database # database name 
        self.project = project # project name
    
    def run(self):
        print "Clone repository in local"
        r = cloneRepoLocally(self.repo)
        if not(r==False):
            self.localRepoPath = tempDir+"/"+r # path to the repository in local machine
        print "Importing Version Control thread start"
        nc, ni, td = importGit(self.localRepoPath, self.couchdb, self.database, self.project)
        print "Number commits: "+str(nc) +"\n"+"Commits imported: "+str(ni)+"\n"+"time importing: "+str(td)

####################################### SVN ##################################################################

def checkoutSVN(repoAddress, projectName):
    # checkout the svn repository corresponding to the given address
    # into a directory with the same name as prokectName
    client = pysvn.Client()
    client.checkout(repoAddress, tempDir+"/"+projectName)
    
def getSVNinfo(projectName):
    # return the "svn info" command on the given project 
    # it is a dictionary
    client = pysvn.Client()
    log = client.log(tempDir+"/"+projectName)
    return log

def importSVNlogInCouchdb(log, projectName, couchdb, database):
    # import the given log in the given database at the given address of couchdb
    num_commits = 0
    stored = 0
    comm_list = []
    server = Server(couchdb)
    db = server.get_or_create_db(database)
    start_explore = time.clock()
    for l in log:
        commit = Commit()
        rev = l.revision
        # the following is ugly and slow but some genius decided that commit's author was an option field 
        client = pysvn.Client()
        if(not("author" in l)):
            info = client.info2(tempDir+"/"+projectName, rev)[0][1]
            authorName=info.last_changed_author
        else:
            authorName=l.author
        commit.createCommit(l.date, authorName, authorName, l.message, str(rev.number), l.changed_paths, projectName)       
        comm_list.append(commit)       
        num_commits +=1
        if(num_commits%100 == 0):
            sys.stdout.write('.')
            sys.stdout.flush()
            #save commit in couchdb
            for c in comm_list:
                ex = c.commitToDatabase(server, db)
                if ex:
                    stored += 1
            comm_list = [] # empty list
    for c in comm_list:
        ex = c.commitToDatabase(server, db)
        if ex:
            stored += 1
    comm_list = [] # empty list
    end_explore = time.clock()
    return num_commits, stored, end_explore-start_explore

class MainSVNThread(threading.Thread):
    # thread to import in couchdb commits from svn
    
    def __init__(self, projectRepoAddress, couchdb, database, project):
        threading.Thread.__init__(self)
        self.projectRepoAddress = projectRepoAddress # repository address
        self.couchdb = couchdb # couchdb address
        self.database = database # databse name 
        self.project = project # name of the project
    
    def run(self):
        print "Importing svn"
        checkoutSVN(self.projectRepoAddress, self.project)
        print " checked out"
        log = getSVNinfo(self.project)
        print " got svn log"
        num, stored, timeImp =  importSVNlogInCouchdb(log, self.project, self.couchdb, self.database)
        print "Number commits: "+str(num) +"\n"+"Commits imported: "+str(stored)+"\n"+"time importing: "+str(timeImp)